package net.piggy.core.socket.handler;


import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import net.piggy.core.mybatis.mapper.ApplicationInterfaceMethod;
import net.piggy.core.model.HttpStatement;
import net.piggy.core.mybatis.factory.MybatisSqlSessionFactory;
import net.piggy.core.socket.common.AgreementConstant;
import net.piggy.core.socket.common.GatewayResult;
import net.piggy.core.socket.parser.RequestParser;
import net.piggy.core.socket.parser.ResponseParser;
import net.piggy.core.util.GatewayConfigUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;


public class GatewayServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    private final Logger logger = LoggerFactory.getLogger(GatewayServerHandler.class);


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
        // todo record log
        logger.info("网关接收请求【全局】 uri：{} method：{}", request.uri(), request.method());

        Channel channel = ctx.channel();

        RequestParser parser = new RequestParser(request);
        String uri = parser.getUri();

        HttpStatement httpStatement = GatewayConfigUtil.getGatewayConfig().getHttpStatement(uri);
        if(httpStatement==null){
            SqlSessionFactory sqlSessionFactory = MybatisSqlSessionFactory.getSqlSessionFactory();
            SqlSession sqlSession = sqlSessionFactory.openSession();
            ApplicationInterfaceMethod mapper = sqlSession.getMapper(ApplicationInterfaceMethod.class);
            httpStatement = mapper.selectGatewayMethodByUri(uri);
            sqlSession.close();
            if(httpStatement==null){
                DefaultFullHttpResponse response = new ResponseParser().parse(GatewayResult.buildError(AgreementConstant.ResponseCode._403.getCode(), "url is not exist"));
                channel.writeAndFlush(response);
                return;
            }
            String applicationName = httpStatement.getApplicationName();
            List<String> applicationUris = GatewayConfigUtil.getGatewayConfig().getApplicationUris(uri);
            if(applicationUris==null){
                applicationUris = new ArrayList<>();
                GatewayConfigUtil.getGatewayConfig().putApplication(applicationName, applicationUris);
            }
            applicationUris.add(uri);
            GatewayConfigUtil.getGatewayConfig().putHttpStatement(uri, httpStatement);

        }
        request.retain();
        channel.attr(AgreementConstant.HTTP_STATEMENT).set(httpStatement);
        ctx.fireChannelRead(request);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws ExecutionException, InterruptedException {
        HttpStatement httpStatement = ctx.channel().attr(AgreementConstant.HTTP_STATEMENT).get();
        if(httpStatement!=null){
            ChannelFuture close = ctx.channel().close();
            logger.warn("channelInactive uri -> {}  close --> {}", httpStatement.getUri(), close.get());
        }
    }
}